package com.xvyy.tingshu.account.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.xvyy.tingshu.account.mapper.UserAccountMapper;
import com.xvyy.tingshu.account.service.MqOpsService;
import com.xvyy.tingshu.account.service.UserAccountService;
import com.xvyy.tingshu.common.execption.TsException;
import com.xvyy.tingshu.model.account.UserAccount;
import com.xvyy.tingshu.vo.account.AccountLockResultVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;

/**
 * ClassName: MqOpsServiceImpl
 * Package: com.xvyy.tingshu.account.service.impl
 *
 * @Description:
 * @Author: xvyy
 * @Create: 2025/1/13 - 20:25
 * @Version: v1.0
 */
@Service
public class MqOpsServiceImpl implements MqOpsService {

    @Autowired
    private UserAccountMapper userAccountMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private UserAccountService userAccountService;

    @Override
    public void userAccountInit(String userId) {

        UserAccount userAccount = new UserAccount();
        userAccount.setUserId(Long.parseLong(userId));
        userAccountMapper.insert(userAccount);
    }

    @Override
    public void unlock(String orderNo) {
        // 1. 从redis中查询锁记录
        // 1.1 锁定记录key
        String userAccountLock = "user:account:data" + orderNo;
        // 1.2 重复消息锁key
        String msgRepeatLockKey = "msg:repeat:" + orderNo;
        String lockStr = stringRedisTemplate.opsForValue().get(userAccountLock);
        // 1.3 判断是否为空
        if (StringUtils.isEmpty(lockStr)) {
            // 如果为空，说明已经解锁或者扣减过了，方法直接返回
            return;
        }
        // 2. 从redis中获取锁定记录
        AccountLockResultVo accountLockResultVo = JSONObject.parseObject(lockStr, AccountLockResultVo.class);
        Long userId = accountLockResultVo.getUserId();
        BigDecimal amount = accountLockResultVo.getAmount();
        String content = accountLockResultVo.getContent();
        try {
            Boolean aBoolean = stringRedisTemplate.opsForValue().setIfAbsent(msgRepeatLockKey, "1");
            if (aBoolean) {
                // 3. 解锁
                userAccountMapper.unLock(userId, amount);
                // 4.记录流水
                userAccountService.log(userId, "解锁" + content, "1203", amount, orderNo);
                // 5.将锁定记录从Redis中删除掉
                stringRedisTemplate.delete(userAccountLock);
            }
        } catch (Exception e) {
            throw new TsException(201, "解锁用户账户余额失败");
        } finally {
            // 6. 兜底删除幂等性锁
            stringRedisTemplate.delete(msgRepeatLockKey);
        }
    }

    @Override
    public void minus(String orderNo) {
        // 1. 从redis中查询锁记录
        String userAccountResultKey = "user:account:data:" + orderNo;
        String msgRepeatLockKey = "msg:repeat:" + orderNo;
        String lockStr = stringRedisTemplate.opsForValue().get(userAccountResultKey);
        if (StringUtils.isEmpty(lockStr)) { // 解决幂等性
            return;
        }
        // 2. 获取数据
        AccountLockResultVo accountLockResultVo = JSONObject.parseObject(lockStr, AccountLockResultVo.class);
        Long userId = accountLockResultVo.getUserId();
        BigDecimal amount = accountLockResultVo.getAmount();
        String content = accountLockResultVo.getContent();
        try {
            Boolean aBoolean = stringRedisTemplate.opsForValue().setIfAbsent(msgRepeatLockKey, "1");
            if (aBoolean) {
                // 3. 扣减用户账户余额
                userAccountMapper.minus(userId, amount);
                // 4. 记录流水
                userAccountService.log(userId, "消费" + content, "1204", amount, orderNo);
                // 5. 将锁定记录从Redis中删除掉
                stringRedisTemplate.delete(userAccountResultKey);
            }
        } catch (Exception e) {
            throw new TsException(201, "扣减用户账户余额失败");
        } finally {
            // 6. 兜底删除幂等性锁
            stringRedisTemplate.delete(msgRepeatLockKey);
        }
    }
}
